package com.dingding.order.core.pay.biz.impl;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.dingding.common.core.base.daox.IBaseDaoX;
import com.dingding.common.core.base.dto.ResponseEntity;
import com.dingding.common.core.beans.UserLogin;
import com.dingding.common.core.beans.UserTaxiOrdert;
import com.dingding.common.core.beans.Useraccountdetail;
import com.dingding.common.core.beans.Userdetail;
import com.dingding.common.core.beans.special.Specialuserlogin;
import com.dingding.common.core.message.shotmsg.ShotMessageBuilder;
import com.dingding.common.core.model.push.PushModel;
import com.dingding.common.core.push.pushmsg.PushData;
import com.dingding.common.core.push.pushmsg.PushMsg;
import com.dingding.common.core.util.DateFormatUtil;
import com.dingding.common.core.util.JSONUtil;
import com.dingding.common.core.util.ToolUtil;
import com.dingding.facade.account.user.service.IUserAccountService;
import com.dingding.facade.queue.dto.push.PushRequestDTO;
import com.dingding.facade.queue.enums.ClientType;
import com.dingding.facade.queue.enums.PushType;
import com.dingding.facade.queue.enums.RoleType;
import com.dingding.facade.queue.facade.IQueueFacade;
import com.dingding.facade.user.facade.passanger.coupon.IUserCouponFacade;
import com.dingding.facade.user.service.IUserInfoFacade;
import com.dingding.facade.user.service.IUserLoginFacade;
import com.dingding.order.code.order.OrderStatus;
import com.dingding.order.core.pay.biz.IPayNotifyService;
import com.dingding.order.core.pay.biz.pay.IPaymentService;
import com.dingding.order.core.pay.dao.IPayUserOrderDao;
import com.dingding.order.core.pay.dao.ITaxiOrderPayDao;
import com.dingding.order.dto.pay.ReqTaxiOneLinePayDTO;
import com.dingding.order.dto.pay.TaxiOrderPayPushDTO;

/**
 * 
 * @ClassName: IPayNotifyService 
 * @Description: 支付成功后相关业务操作
 * @author CHEHAUNBO 
 * @date 2016年7月7日 上午9:10:40
 * 
 */
@Component("payNotifyServiceV2")
public class PayNotifyServiceImplV2 implements IPayNotifyService {

	private Logger log = Logger.getLogger(PayNotifyServiceImplV2.class);

	/**
	 * 出租车订单DAO
	 */
	@Resource(name = "taxiOrderPayDao")
	private ITaxiOrderPayDao taxiOrderDao;

	/**
	 * 用户信息服务接口
	 */
	@Resource(name = "userLoginService")
	private IUserLoginFacade userLoginFacade;

	/**
	 * 订单正式表支付操作DAO
	 */
	@Resource(name = "payUserOrderDao")
	private IPayUserOrderDao payUserOrderDao;

	/**
	 * 支付操作service
	 */
	@Resource(name = "dingbiPayment")
	private IPaymentService paymentService;

	@Resource(name = "queueService")
	private IQueueFacade queueFacade;

	@Resource(name = "userAccountService")
	private IUserAccountService userAccountService;

	@Resource(name = "userInfoService")
	private IUserInfoFacade userInfoFacade;
	
	@Resource(name = "baseDaoX")
	private IBaseDaoX baseDaoX;
	
	
	@Resource(name = "_userCouponFacade")
	private IUserCouponFacade userCouponFacade;
	
	/**
	 * 
	 * 第三方平台或者叮币支付成功后，更改订单状态
	 * 
	 * @Title: orderPayNotify 
	 * @param taxiOrderId 出租车订单ID
	 * @param transactionType 交易类型  1：线上 2：线下
	 * @return boolean true 成功 false 失败
	 * @author CHEHAUNBO
	 * @since V2.3.0
	 * 
	 */
	@Override
	@Transactional(propagation = Propagation.REQUIRED)
	public boolean paySuccessUpdateOrderStatus(String taxiOrderId, Integer transactionType, boolean isCallback) {

		// 获取订单信息
		UserTaxiOrdert userTaxiOrdert = taxiOrderDao.getUserTaxiOrder(taxiOrderId);
		
		if (userTaxiOrdert == null) {
			log.error("第三方平台支付成功后，更改出租车订单状态失败，原因没有获取到当前订单；订单ID：" + taxiOrderId);
			return false;
		}
		

		try {
			
//			updateUserCouponStatus(taxiOrderId);

			if(transactionType == 1){
				// 给司机转账
				userAccountService.transferAccountsDriver(userTaxiOrdert.getGrabOrderUserId(), userTaxiOrdert.getTotalMoney());
			}

			// 累计接乘、累计搭乘
			addUserDetail(userTaxiOrdert.getPlaceOrderUserId(), userTaxiOrdert.getGrabOrderUserId(), userTaxiOrdert.getDistance());
			
			//出租车支付成功后添加交易明细
			addTradeDetail(userTaxiOrdert);
			
			if (isCallback) { // 第三方支付回调
				if (userTaxiOrdert.getPayMoney().compareTo(new BigDecimal(0)) > 0) { // 叮币扣款
					ReqTaxiOneLinePayDTO reqTaxiOneLinePayDTO = new ReqTaxiOneLinePayDTO();
					reqTaxiOneLinePayDTO.setPassengerId(userTaxiOrdert.getPlaceOrderUserId());
					reqTaxiOneLinePayDTO.setPayMoney(userTaxiOrdert.getPayMoney());
					paymentService.payment(reqTaxiOneLinePayDTO, new ResponseEntity<ReqTaxiOneLinePayDTO>());
				}
			}
			// 订单迁移
			payUserOrderDao.orderPayUpdateOrderStatus(userTaxiOrdert);
			// 订单删除
			taxiOrderDao.delete(userTaxiOrdert);

		} catch (Exception e) {
			log.error("第三方平台支付成功后，更改订单状态失败！订单ID:" + taxiOrderId, e);
			return false;
		}

		// 叮币支付 - 通知推送
		payPush(userTaxiOrdert.getGrabOrderUserId(), taxiOrderId, transactionType);

		//通知推送
		this.payNoticePush(userTaxiOrdert.getGrabOrderUserId(), taxiOrderId, transactionType);
		
		return true;

	}
	
	
	/**
	 * 
	 * @Description: 将优惠券改为已使用状态
	 * @param taxiOrderId 出租订单ID
	 * @author CHEHUANBO
	 * @version V2.6.2
	 * 
	 */
	private void updateUserCouponStatus(String taxiOrderId) {

		// 获取订单信息
		UserTaxiOrdert userTaxiOrdert = taxiOrderDao.getUserTaxiOrder(taxiOrderId);

		if (userTaxiOrdert != null && userTaxiOrdert.getCouponId() != 0) {

			Map<String, Object> reqMap = new HashMap<String, Object>();
			reqMap.put("couponId", userTaxiOrdert.getCouponId());
			reqMap.put("updateType", 2);

			try {
				userCouponFacade.updateUserCouponStatus(reqMap);
			} catch (Exception e) {
				log.info("远程调用设置用户优惠券状态为已使用出现异常!taxiOrderId :" + taxiOrderId, e);
			}

		}

	}
	

	/**
	 * @Description:支付成功后添加交易明细
	 * @author fengshuonan
	 * @since 2.4
	 */
	@Transactional(propagation = Propagation.REQUIRED)
	private void addTradeDetail(UserTaxiOrdert userTaxiOrdert) {
		
		//添加发单的人的交易明细
		Useraccountdetail useraccountdetail = new Useraccountdetail();
		useraccountdetail.setUadId(ToolUtil.getUid());
		useraccountdetail.setUserId(userTaxiOrdert.getPlaceOrderUserId());
		useraccountdetail.setTradeMoney(userTaxiOrdert.getTotalMoney());
		useraccountdetail.setTradeType(2);// 交易类型 (1:收入 2: 支出 3:提现 4:取消(已支付)订单退款)
		useraccountdetail.setTradeTime(new Date());
		if(userTaxiOrdert.getPayMoney() == null){
			userTaxiOrdert.setPayMoney(new BigDecimal(0));
		}
		useraccountdetail.setActualPaymentMoney(userTaxiOrdert.getTotalMoney());
		useraccountdetail.setCouponMoney(new BigDecimal(0));
		
		//添加抢单的人的交易明细
		Useraccountdetail grabDetail = new Useraccountdetail();
		grabDetail.setUadId(ToolUtil.getUid());
		grabDetail.setUserId(userTaxiOrdert.getGrabOrderUserId());
		grabDetail.setTradeMoney(userTaxiOrdert.getTotalMoney());
		grabDetail.setTradeType(1);// 交易类型 (1:收入 2: 支出 3:提现 4:取消(已支付)订单退款)
		grabDetail.setTradeTime(new Date());
		if(userTaxiOrdert.getPayMoney() == null){
			userTaxiOrdert.setPayMoney(new BigDecimal(0));
		}
		grabDetail.setActualPaymentMoney(userTaxiOrdert.getTotalMoney());
		grabDetail.setCouponMoney(new BigDecimal(0));
		
		try {
			this.baseDaoX.save(useraccountdetail);
			this.baseDaoX.save(grabDetail);
		} catch (Exception e) {
			log.error("出租车单完成后，添加交易明细失败！",e);
		}
		
	}

	/**
	 * 
	 * @Title: updateUserDetail 
	 * @Description:  累计接乘、累计搭乘
	 * @param placeOrderUserId 下单用户(乘客)
	 * @param grabOrderUserId	抢单用户(司机)
	 * @param distance	订单里程
	 * @author YHQ 
	 * @since V2.3.0
	 * @return void    返回类型
	 * 
	 */
	public void addUserDetail(String placeOrderUserId,String grabOrderUserId,BigDecimal distance){
		
		// 获取乘客用户明细
		Userdetail passengerDetail = userInfoFacade.getUserDetail(placeOrderUserId);
		
		// 乘客累计搭乘
		passengerDetail.setTotalTake(passengerDetail.getTotalTake().add(distance));
		
		userInfoFacade.updateUserDetail(passengerDetail);
	}
	
	/**
	 * 
	 * 支付成功后消息推送
	 * 
	 * 订单支付成功后；需要告知车主已经支付成功，此方法由此而来
	 * 
	 * @Title: payPush 
	 * @param driverId 车主ID
	 * @param orderId 订单ID
	 * @param transactionType 交易类型 1：线上支付 2：线下支付
	 * @author CHEHAUNBO
	 * @since V2.3.0
	 * 
	 */
	public void payPush(String driverId, String orderId, Integer transactionType) {
		// 根据用户ID(车主)获取别名
		Specialuserlogin userInfo = this.baseDaoX.getById(driverId, Specialuserlogin.class);
		
		if (userInfo != null && ToolUtil.isNotBlank(userInfo.getAliasId())) {

			// 创建推送Bean
			PushData pushData = new PushData();
			// 推送序号(时间戳)
			pushData.setRequestNumber(DateFormatUtil.getTimeInMillis().toString());
			// 推送时间
			pushData.setRequestTime(DateFormatUtil.yyyy_MM_dd_HHmmss());
			// 模块
			pushData.setModular("passengerPayPush");

			TaxiOrderPayPushDTO payPushDTO = new TaxiOrderPayPushDTO();
			payPushDTO.setOrderStatus(OrderStatus.ORDER_STATUS_COMPLETE);
			payPushDTO.setOid(orderId);
			payPushDTO.setTransactionType(transactionType);
			payPushDTO.setPublishType(2);
			// 推送内容
			pushData.setResponseBody(payPushDTO);

			PushRequestDTO pushRequestDTO = new PushRequestDTO();
			pushRequestDTO.setAlert("乘客已支付，请注意查收！");
			pushRequestDTO.setMsgTitle("乘客已支付，请注意查收！");
			pushRequestDTO.setAliasId(userInfo.getAliasId());
			pushRequestDTO.setAlert(PushMsg.PASSENGER_PAY);
			pushRequestDTO.setRoleType(RoleType.Driver);
			pushRequestDTO.setPushContent(JSONUtil.toJSONString(pushData));
			ClientType clientType = null;
			if ("iOS".equals(userInfo.getClientType())) { // iOS
				clientType = ClientType.iOS;
			} else { // Android
				clientType = ClientType.Android;
			}
			pushRequestDTO.setClientType(clientType);
			pushRequestDTO.setPushType(PushType.alert_msgcontent);

			// 添加消息到队列中
			queueFacade.addPushToQueue(JSONUtil.toJSONString(pushRequestDTO));

		}

	}
	
	/**
	 * 
	 * 支付成功后通知消息推送
	 * 
	 * 订单支付成功后；需要告知车主已经支付成功，此方法由此而来
	 * 
	 * @Title: payNoticePush 
	 * @param driverId 车主ID
	 * @param orderId 订单ID
	 * @param transactionType 交易类型 1：线上支付 2：线下支付
	 * @author CHEHAUNBO
	 * @since V2.3.0
	 * 
	 */
	public void payNoticePush(String driverId, String orderId, Integer transactionType) {
		
		// 根据用户ID(车主)获取别名
		Specialuserlogin userInfo = this.baseDaoX.getById(driverId, Specialuserlogin.class);
		if (userInfo != null && ToolUtil.isNotBlank(userInfo.getAliasId())) {
			
			// 创建推送Bean
			PushData pushData = new PushData();
			// 推送序号(时间戳)
			pushData.setRequestNumber(DateFormatUtil.getTimeInMillis().toString());
			// 推送时间
			pushData.setRequestTime(DateFormatUtil.yyyy_MM_dd_HHmmss());
			// 模块
			pushData.setModular("newsNoticePush");
			
			String content = "乘客已支付";
			
			// 推送内容
			pushData.setResponseBody(PushModel.noticeModel(1, content, null));
			
			PushRequestDTO pushRequestDTO = new PushRequestDTO();
			// 别名
			pushRequestDTO.setAliasId(userInfo.getAliasId());
			// 通知推送内容
			pushRequestDTO.setPushContent(JSONUtil.toJSONString(pushData));
			ClientType clientType = null;
			if ("iOS".equals(userInfo.getClientType())) { // iOS
				clientType = ClientType.iOS;
			} else { // Android
				clientType = ClientType.Android;
			}
			pushRequestDTO.setClientType(clientType);
			pushRequestDTO.setPushType(PushType.msgcontent);
			
			// 添加消息到队列中
			queueFacade.addPushToQueue(JSONUtil.toJSONString(pushRequestDTO));
			
		}
		
	}

	/**
	 * 
	 * @Title: pushNoticeMessage 
	 * @Description: 支付回调推送通知
	 * @param userInfo
	 * @author YHQ 
	 * @since V2.3.2
	 * @return void    返回类型
	 */
	public void pushNoticeMessage(UserLogin userInfo){
		
		// 创建推送Bean
		PushData pushData = new PushData();
		// 推送序号(时间戳)
		pushData.setRequestNumber(DateFormatUtil.getTimeInMillis().toString());
		// 推送时间
		pushData.setRequestTime(DateFormatUtil.yyyy_MM_dd_HHmmss());
		// 模块
		pushData.setModular("newsNoticePush");

		
		// 推送内容
		pushData.setResponseBody(PushModel.noticeModel(1, ShotMessageBuilder.getPassengerPayMsg(""), null));

		PushRequestDTO pushRequestDTO = new PushRequestDTO();
		pushRequestDTO.setAliasId(userInfo.getAliasId());
		pushRequestDTO.setAlert(PushMsg.PASSENGER_PAY);
		pushRequestDTO.setPushContent(JSONUtil.toJSONString(pushData));
		ClientType clientType = null;
		if (userInfo.getLoginEquipment() == 1) { // iOS
			clientType = ClientType.iOS;
		} else { // Android
			clientType = ClientType.Android;
		}
		pushRequestDTO.setClientType(clientType);
		pushRequestDTO.setPushType(PushType.alert_msgcontent);

		// 添加消息到队列中
		queueFacade.addPushToQueue(JSONUtil.toJSONString(pushRequestDTO));
		
	}
	
}
